package com.elric.mall.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.elric.mall.common.exception.ApiException;
import com.elric.mall.dto.FileAntdDto;
import com.elric.mall.dto.TaskDto;
import com.elric.mall.enums.ImportType;
import com.elric.mall.mapper.ProgrammeProjectMapper;
import com.elric.mall.mapper.TaskMapper;
import com.elric.mall.mapper.TaskUnitMapper;
import com.elric.mall.mapper.ZgBaseUpperUnitMapper;
import com.elric.mall.model.*;
import com.elric.mall.service.TaskService;
import com.elric.mall.service.UmsFileInfoService;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 实现功能：计划任务实现层
 *
 * @author 作者[Yuxuan.he]
 * @version 1.0.00  2021-09-16 11:21
 */
@Service
public class TaskServiceImpl implements TaskService {
    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private TaskUnitMapper taskUnitMapper;

    @Autowired
    private UmsFileInfoService umsFileInfoService;

    @Autowired
    private ZgBaseUpperUnitMapper baseUpperUnitMapper;

    @Autowired
    private ProgrammeProjectMapper programmeProjectMapper;

    private static final String REL_TYPE = "TASK";

    private void validateTask(Task task) {
        TaskExample example = new TaskExample();
        TaskExample.Criteria criteria = example.createCriteria();
        if (StrUtil.isNotBlank(task.getId())) {
            criteria.andIdNotEqualTo(task.getId());
        }
        criteria.andUpperUnitEqualTo(task.getUpperUnit());
        // 查找是否有重复大单位的数据
        Long count = taskMapper.countByExample(example);
        if (count > 0) {
            throw new ApiException("已存在相同大单位任务，无法保存！");
        }
    }

    /**
     * 添加任务-大单位关联数据
     * @param taskId
     * @param unitList
     * @param umsAdmin
     */
    private void addUnitRelation(String taskId, List<String> unitList, UmsAdmin umsAdmin) {
        if (StrUtil.isNotBlank(taskId)) {
            // 先清理该任务以前的关联关系
            TaskUnitExample taskUnitExample = new TaskUnitExample();
            taskUnitExample.createCriteria().andTaskIdEqualTo(taskId);
            taskUnitMapper.deleteByExample(taskUnitExample);

            ZgBaseUpperUnitExample example = new ZgBaseUpperUnitExample();
            example.createCriteria().andIdIn(unitList);
            example.setOrderByClause("order_num asc");
            List<ZgBaseUpperUnit> units = baseUpperUnitMapper.selectByExample(example);
            if (CollectionUtil.isNotEmpty(units)) {
                List<TaskUnit> taskUnits = new ArrayList<>();
                units.stream().forEach(u -> {
                    TaskUnit taskUnit = new TaskUnit();
                    taskUnit.setId(IdUtil.fastUUID());
                    taskUnit.setTaskId(taskId);
                    taskUnit.setUnitId(u.getId());
                    taskUnit.setUnitName(u.getUnitName());
                    taskUnit.setCreateId(umsAdmin.getId());
                    taskUnit.setCreateName(umsAdmin.getNickName());
                    taskUnit.setCreateTime(new DateTime());
                    taskUnit.setUploadNum((long) 0);
                    taskUnit.setUploadAmount(new BigDecimal("0"));
                    taskUnits.add(taskUnit);
                });
                taskUnitMapper.insertBatch(taskUnits);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int create(TaskDto.Params task, UmsAdmin umsAdmin) {
//        validateTask(task);
        task.setStatus("open");
        task.setId(IdUtil.fastUUID());
        task.setUpdateTime(new DateTime());
        task.setCreateTime(new DateTime());
        task.setCreateName(umsAdmin.getNickName());
        task.setCreateId(umsAdmin.getId());
        // 添加附件关联关系
        umsFileInfoService.addRelation(task.getId(), REL_TYPE, task.getFiles());
        // 添加大单位关联关系
        addUnitRelation(task.getId(), task.getUnitList(), umsAdmin);
        return taskMapper.insert(task);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int update(TaskDto.Params task, UmsAdmin umsAdmin) {
//        validateTask(task);
        task.setUpdateTime(new DateTime());
        // 添加附件关联关系
        umsFileInfoService.addRelation(task.getId(), REL_TYPE, task.getFiles());
        // 添加大单位关联关系
        addUnitRelation(task.getId(), task.getUnitList(), umsAdmin);
        return taskMapper.updateByPrimaryKeySelective(task);
    }

    @Override
    public TaskDto.Detail findById(String id) {
        TaskDto.Detail dto = new TaskDto.Detail();
        Task task = taskMapper.selectByPrimaryKey(id);
        BeanUtils.copyProperties(task, dto);

        // 查询附件信息
        List<FileAntdDto> files = umsFileInfoService.findAntdFileById(id);
        dto.setFiles(files);

        // 查询大单位信息
        TaskUnitExample taskUnitExample = new TaskUnitExample();
        taskUnitExample.createCriteria().andTaskIdEqualTo(id);
        List<TaskUnit> taskUnits = taskUnitMapper.selectByExample(taskUnitExample);
        dto.setUnitList(taskUnits.stream().map(TaskUnit::getUnitId).collect(Collectors.toList()));
        return dto;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int delete(String id) {
        // 删除对应的计划项目信息
        programmeProjectMapper.deleteByTaskId(id);

        // 删除任务信息
        taskMapper.deleteByPrimaryKey(id);

        // 删除计划-大单位数据
        TaskUnitExample example = new TaskUnitExample();
        example.createCriteria().andTaskIdEqualTo(id);
        taskUnitMapper.deleteByExample(example);

        // 删除关联的附件数据
        umsFileInfoService.delFileByEntityId(id);
        return 1;
    }

    @Override
    public List<Task> list(Integer pageSize, Integer pageNum, Task task) {
        PageHelper.startPage(pageNum, pageSize);
        TaskExample example = new TaskExample();
        if(!StringUtils.isEmpty(task.getName())) {
            example.createCriteria().andNameLike("%"+task.getName()+ "%");
        }
        return taskMapper.selectByExample(example);
    }

    @Override
    public List<Task> findAll() {
        return taskMapper.findAll();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertBatch(List<Task> list, ImportType importType) {
        if (importType == ImportType.full) {
            TaskExample example = new TaskExample();
            taskMapper.deleteByExample(example);
        }
        list.stream().forEach(l -> {
            l.setId(IdUtil.fastUUID());
        });
        return taskMapper.insertBatch(list);
    }

    @Override
    public List<TaskUnit> findUnitByTaskId(String taskId) {
        return taskUnitMapper.selectByTaskId(taskId);
    }

    @Override
    public void updateTaskInfo(String taskUnitId) {
        TaskUnit taskUnit = taskUnitMapper.selectByPrimaryKey(taskUnitId);
        if (!Objects.isNull(taskUnit)){
            ProgrammeProjectExample example = new ProgrammeProjectExample();
            example.createCriteria().andTaskUnitIdEqualTo(taskUnitId);
            List<ProgrammeProject> list = programmeProjectMapper.selectByExample(example);

            // 计算任务条数
            Integer num = CollectionUtil.isEmpty(list)?0: list.size();
            taskUnit.setUploadNum(Integer.toUnsignedLong(num));

            // 计算任务总金额
            BigDecimal sum = list.stream().map(p -> {
                if (!Objects.isNull(p.getGhztz())) {
                    return p.getGhztz();
                }
                return new BigDecimal("0");
            }).reduce((t, i) -> t.add(i)).orElse(new BigDecimal("0"));
            taskUnit.setUploadAmount(sum);
            taskUnitMapper.updateByPrimaryKey(taskUnit);
        } else {
            throw new ApiException("未找到关联的任务信息，请确认！");
        }
    }

    @Override
    public Map<String, Object> statistics() {
        Map<String, Object> map = taskMapper.statistics();
        map.putAll(taskMapper.unitStatistics());
        return map;
    }
}
